#ifndef __LSZ_ANY_H__
#define __LSZ_ANY_H__

#include "LszTypes.h"

namespace Lsz
{
class	AnyDict;
class	AnyVector;
class	Point;
class	Rect;
struct	Pair;

class LSZCORE_EXPORT Any
{
public:
	enum Type
	{
		INVALID		= -1,
		INT32		= 0,
		FLOAT		= 1,
		STRING		= 2,
		WSTRING		= 3,
		ANYDICT		= 4,
		ANYVECTOR	= 5,
		INT64		= 6,
		GENERIC		= 7,
		POINT		= 9,
		RECT		= 10,
		PAIR		= 13,
	};

	~Any();

	Any();
	Any(const Any&);
	Any(int32_t);
	Any(float);
	Any(double);
	Any(int64_t);
	Any(const char* , int count = 0);
	Any(const McWChar* , int count = 0);
	Any(const void* , int);
	Any(const AnyVector&);
	Any(const AnyDict&);
	Any(const Point&);
	Any(const Rect&);
	Any(const Pair&);

	void	set(const Any&);
	void	set(int32_t);
	void	set(float);
	void	set(double);
	void	set(const char* , int size = 0);
	void	set(const McWChar* , int size = 0);
	void	set(const void* , int size);
	void	set(const AnyDict&);
	void	set(int64_t);
	void	set(const AnyVector&);
	void	set(const Point&);
	void	set(const Rect&);
	void	set(const Pair&);

	Any &operator	=(const Any&);
	Any &operator	=(const char*);
	Any &operator	=(int32_t);
	Any &operator	=(int64_t);
	Any &operator	=(float);
	Any &operator	=(double);
	Any &operator	=(const void*);
	Any &operator	=(const AnyVector&);
	Any &operator	=(const AnyDict&);
	Any &operator	=(const Point&);
	Any &operator	=(const Rect&);
	Any &operator	=(const Pair&);

	bool operator	==(const Any&) const;
	bool operator	<(const Any&) const;
	bool operator	>(const Any&) const;
	bool operator	!=(const Any&) const;

	int64_t		asInt64() const;
	int32_t		asInt32() const;
	double		asDouble() const;

	inline double asFloat() const
	{
		return asDouble();
	}

	char*		asString() const;
	McWChar*	asWString() const;
	void*		asGeneric() const;
	AnyVector&	asVector() const;
	AnyDict&	asDict() const;
	Point&	asPoint() const;
	Rect&		asRect() const;
	Pair&		asPair() const;

	inline int64_t asInt64(int64_t dfl) const
	{
		return isInt64() ? asInt64() : dfl;
	}

	inline int32_t asInt32(int32_t dfl) const
	{
		return isInt32() ? asInt32() : dfl;
	}

	inline double asDouble(double dfl) const
	{
		return isDouble() ? asDouble() : dfl;
	}

	inline double asFloat(double dfl) const
	{
		return isDouble() ? asDouble() : dfl;
	}

	inline const char* asString(const char* dfl) const
	{
		return isString() ? asString() : dfl;
	}

	inline const McWChar* asWString(const McWChar* dfl) const
	{
		return isWString() ? asWString() : dfl;
	}

	inline void* asGeneric(void* dfl) const
	{
		return isGeneric() ? asGeneric() : dfl;
	}

	operator	int64_t() const;
	operator	int32_t() const;
	operator float() const;
	operator double() const;
	operator char* () const;
	operator McWChar* () const;
	operator void* () const;
	operator AnyVector& () const;
	operator AnyDict& () const;
	operator Point& () const;
	operator Rect& () const;
	operator Pair& () const;

	inline bool isTrue() const
	{
		return operator bool();
	}

	inline bool isFalse() const
	{
		return !operator bool();
	}

	operator		bool() const;
	bool operator	!() const;

	inline Type type() const
	{
		return _type;
	}

	int		size() const;
	void	invalidate();

	inline bool isValid() const
	{
		return _type != INVALID;
	}

	inline bool isInt32() const
	{
		return type() == INT32;
	}

	inline bool isInt64() const
	{
		return type() == INT64;
	}

	inline bool isFloat() const
	{
		return type() == FLOAT;
	}

	inline bool isDouble() const
	{
		return type() == FLOAT;
	}

	inline bool isString() const
	{
		return type() == STRING;
	}

	inline bool isWString() const
	{
		return type() == WSTRING;
	}

	inline bool isDict() const
	{
		return type() == ANYDICT;
	}

	inline bool isVector() const
	{
		return type() == ANYVECTOR;
	}

	inline bool isGeneric() const
	{
		return type() == GENERIC;
	}

	inline bool isPoint() const
	{
		return type() == POINT;
	}

	inline bool isRect() const
	{
		return type() == RECT;
	}

	inline bool isPair() const
	{
		return type() == PAIR;
	}

	inline bool isText() const
	{
		return isString() || isWString();
	}

	inline bool isInt() const
	{
		return isInt32() || isInt64();
	}

	Any		toString() const;
	Any		toWString() const;

	int32_t toInt32() const;
	int64_t toInt64() const;
	double	toDouble() const;

	double toFloat() const
	{
		return toDouble();
	}

	static const char*	typeName(int type);
	static Any			strcat(const Any& a1, const Any& a2);
	AnyVector			split(const Any& sep) const;
	static Any			sprintf(const char* fmt, ...);
	Any					replace(const Any& from, const Any& to) const;
	Any					substr(int begin, int end) const;

	static const Any&	null();
	bool				isNull() const;
	static const Any&	invalid();

private:
	void*	value() const;
	void	_destroy();
	void	_checktype(Type type, const char* typeName = 0) const;

	union
	{
		int32_t		_i32;
		int64_t		_i64;
		double		_dbl;
		char*		_str;
		McWChar*	_wstr;
		AnyVector*	_vect;
		AnyDict*	_dict;
		void*		_value;
	};
	int			_size;
	Type		_type;

	explicit	Any(int, int, int);
};

#define Any_Null	(Any::invalid())

LSZCORE_EXPORT bool operator	==(const Any& l, const char* r);
LSZCORE_EXPORT bool operator	!=(const Any& l, const char* r);
LSZCORE_EXPORT bool operator	==(const Any& l, const McWChar* r);
LSZCORE_EXPORT bool operator	!=(const Any& l, const McWChar* r);

//////////////////////////////////////////////////////////////////////////
#define MCVSPRINTF(Buf, Bufsiz, Fmt)		 \
	char   Buf[Bufsiz];						 \
	Buf[Bufsiz - 1] = 0;					 \
	va_list marker;							 \
	va_start(marker, Fmt);					 \
	vsnprintf(Buf, Bufsiz - 1, Fmt, marker); \
	va_end(marker);							 \
	Buf[Bufsiz - 1] = 0;

//////////////////////////////////////////////////////////////////////////
}

#endif // __LSZ_ANY_H__
